package com.demo.common.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.Claim;
import com.mi.rule.util.EnvKit;
import com.mi.rule.util.StrKit;
import com.mi.rule.util.project.MiException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * Token凭证签发工具
 *
 * @author 王永吉
 */
@Slf4j
@Component
public class JwtKit {
    //签名算法
    private static volatile Algorithm algorithm256 = null;
    //签名验证工具
    private static volatile JWTVerifier jwtVerifier = null;

    /**
     * 生成Token
     *
     * @param param 携带参数
     * @param hour  失效时间(小时)
     * @return Token字符串
     */
    public static String createToken(Map<String, Object> param, long hour) {
        Date withExpiresAt = new Date(new Date().getTime() + (hour * 60 * 60 * 1000));
        if (param == null) {
            param = new HashMap<>(2);
        }
        return JWT.create()
                .withClaim("param", JSON.toJSONString(param))//可读取的参数信息（别存太多）
                .withExpiresAt(withExpiresAt)//超时时间
                .sign(getAlgorithm256()); //signature
    }


    /*** 获取参数对象 ***/
    public static JSONObject getParam(String token) {
        return JSON.parseObject(getClaims(token).get("param").asString());
    }

    /*** 获取Claims ***/
    private static Map<String, Claim> getClaims(String token) {
        try {
            return getJwtVerifier().verify(token).getClaims();
        } catch (MiException e) {
            throw new MiException(ResMsg.ERROR_401);
        }
    }

    //检查失效
    public static boolean check(Object token) {
        try {
            if (StrKit.isBlank(token)) return false;
            getJwtVerifier().verify(token.toString());
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    private static Algorithm getAlgorithm256() {
        if (algorithm256 == null) {
            synchronized (JwtKit.class) {
                if (algorithm256 == null) {
                    algorithm256 = Algorithm.HMAC256(EnvKit.authSecret());
                }
            }
        }
        return algorithm256;
    }

    private static JWTVerifier getJwtVerifier() {
        if (jwtVerifier == null) {
            synchronized (JwtKit.class) {
                if (jwtVerifier == null) {
                    jwtVerifier = JWT.require(getAlgorithm256()).build();
                }
            }
        }
        return jwtVerifier;
    }
}